package com.ttg.web.service.job.impl;

import com.ttg.common.dto.TaskAcctDTO;
import com.ttg.common.dto.TaskBaseDTO;
import com.ttg.common.enums.AccountDimTypeEnum;
import com.ttg.common.enums.AcctSubjectTypeEnum;
import com.ttg.common.enums.IntervalTypeEnum;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.BigDecimalUtil;
import com.ttg.common.utils.BigDecimalUtils;
import com.ttg.common.utils.IntegerUtil;
import com.ttg.common.vo.TaskResultVO;
import com.ttg.model.po.AccountInfoPO;
import com.ttg.model.pojo.CostManageAcctDepositAnalysis;
import com.ttg.web.dao.CostManageAcctDepositAnalysisDao;
import com.ttg.web.service.job.AcctDepositAnalysisJobService;
import com.ttg.web.service.job.JobCommon;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * Description： 直绑/全量账户存款结构分解清算任务
 * Author: chenyou
 * Date: 2025/9/22 10:06
 * Company: ttg
 * Copyright: Copyright (c) 2025
 */
@Slf4j
@Service
public class AcctDepositAnalysisJobServiceImpl extends JobCommon implements AcctDepositAnalysisJobService {

    //计算加权利率过程中保留小数位
    private static final int RATE_SCALE = 8;

    //计算加权利率结果保留小数位
    private static final int RATE_RESULT_SCALE = 2;

    @Autowired
    private CostManageAcctDepositAnalysisDao depositAnalysisDao;

    @Override
    public TaskResultVO acctDepositAnalysis(TaskAcctDTO reqDto) {
        TaskBaseDTO baseDTO = new TaskBaseDTO();
        BeanUtils.copyProperties(reqDto,baseDTO);
        baseDTO = getCheckYearAndMonth(baseDTO);
        BeanUtils.copyProperties(baseDTO,reqDto);

        List<AccountInfoPO> acctList = null;
        if(IntegerUtil.equals(AccountDimTypeEnum.直绑账户.getValue(),reqDto.getAcctDimType())){
            //todo 全部直绑账户数据
            acctList = getBindAcctList();
            execJob(reqDto,acctList);
        }else if(IntegerUtil.equals(AccountDimTypeEnum.全量账户.getValue(),reqDto.getAcctDimType())){
            //todo 全部全量账户数据
            acctList = getAllAcctList();
            execJob(reqDto,acctList);
        }else{// 默认跑批 全部直绑账户和全量账户数据
            //todo 全部直绑账户数据
            acctList = getBindAcctList();
            execJob(reqDto,acctList);
            //todo 全部全量账户数据
            acctList = getAllAcctList();
            execJob(reqDto,acctList);
        }

        return taskReuslt(Status.SUCCESS.getValue(),false,"ok");
    }

    public void execJob(TaskAcctDTO reqDto,List<AccountInfoPO> acctList){
        for(AcctSubjectTypeEnum curr: AcctSubjectTypeEnum.values()){
            acctDepositAnalysis(reqDto,acctList,curr.getValue());
        }
    }


    public void acctDepositAnalysis(TaskAcctDTO reqDto,List<AccountInfoPO> acctList,Integer acctType){
        List<AccountInfoPO> targetAcctList = null;
        if(IntegerUtil.equals(AcctSubjectTypeEnum.对公户.getValue(),acctType)){
            //todo 筛选对公户列表
            targetAcctList = acctList;
        }else if(IntegerUtil.equals(AcctSubjectTypeEnum.个人户.getValue(),acctType)){
            //todo 筛选个人户（储蓄户）列表
            targetAcctList = acctList;
        }


        CostManageAcctDepositAnalysis depositAnalysis = new CostManageAcctDepositAnalysis();
        depositAnalysis.setCmadAcctType(acctType);
        depositAnalysis.setCmadAcctDimType(reqDto.getAcctDimType());
        depositAnalysis.setCmadIntervalType(reqDto.getIntervalType());
        depositAnalysis.setCmadYear(reqDto.getYear());
        depositAnalysis.setCmadMonth(reqDto.getMonth());
        //期末时点余额合计
        BigDecimal lastdayAmtSum = lastdayAmtSum(targetAcctList,reqDto.getIntervalType());
        depositAnalysis.setCmadLastdayAmt(lastdayAmtSum);
        //期间日均余额的合计
        BigDecimal avgAmtSum = avgAmtSum(targetAcctList,reqDto.getIntervalType());
        depositAnalysis.setCmadAvgAmt(avgAmtSum);
        //日均余额的加权合计
        BigDecimal weightRate = weightRate(targetAcctList,reqDto.getIntervalType());
        depositAnalysis.setCmadWeightRate(weightRate);
        //模拟付息
        BigDecimal payInterest = payInterest(avgAmtSum,weightRate);
        depositAnalysis.setCmadPayInterest(payInterest);
        depositAnalysisDao.saveOrUpd(depositAnalysis);
    }

    /**
     * 期末时点余额合计
     * 公式：sum(账户期末时点余额)
     */
    public static BigDecimal lastdayAmtSum(List<AccountInfoPO> acctList,String intervalType){
        Long sumLong = acctList.parallelStream()
                .filter(o -> true)
                .mapToLong(o -> {
                    BigDecimal lastDayAmount = BigDecimal.ZERO;
                    if(IntervalTypeEnum.月度区间.getValue().equals(intervalType)){
                        lastDayAmount = BigDecimalUtil.yuanToFen(o.getLastDayAmount());
                    }else if(IntervalTypeEnum.年度区间.getValue().equals(intervalType)){
                        lastDayAmount = BigDecimalUtil.yuanToFen(o.getYearLastDayAmount());
                    }
                    return lastDayAmount==null?0:lastDayAmount.longValue();
                })
                .sum();
        return new BigDecimal(sumLong);
    }

    /**
     * 期间日均余额合计
     * 公式：sum(账户期间日均余额)
     */
    public static BigDecimal avgAmtSum(List<AccountInfoPO> acctList,String intervalType){
        Long sumLong = acctList.parallelStream()
                .filter(o -> true)
                .mapToLong(o -> {
                    BigDecimal avgDepositAmount = BigDecimal.ZERO;
                    if(IntervalTypeEnum.月度区间.getValue().equals(intervalType)){
                        avgDepositAmount = BigDecimalUtil.yuanToFen(o.getAvgDepositAmount());
                    }else if(IntervalTypeEnum.年度区间.getValue().equals(intervalType)){
                        avgDepositAmount = BigDecimalUtil.yuanToFen(o.getYearAvgDepositAmount());
                    }
                    return avgDepositAmount==null?0:avgDepositAmount.longValue();
                })
                .sum();
        return new BigDecimal(sumLong);
    }

    /**
     * 期间加权利率
     * 公式：sum(单户期间日均余额/sum(期间日均余额) * 单户利率)
     */
    public static BigDecimal weightRate(List<AccountInfoPO> acctList,String intervalType){
        if(IntervalTypeEnum.月度区间.getValue().equals(intervalType)) {
            BigDecimal totalAmt = new BigDecimal(acctList.parallelStream()
                    .filter(o -> true)
                    .mapToLong(o -> {
                        return BigDecimalUtil.yuanToFen(o.getAvgDepositAmount()).longValue();
                    }).sum());

            BigDecimal rate =
                    acctList.parallelStream()
                    .filter(o -> true)
                    .map(o -> {
                        //a = 单户期间日均余额/sum(期间日均余额)
                        BigDecimal a = BigDecimalUtils.div(BigDecimalUtil.yuanToFen(o.getAvgDepositAmount()),totalAmt,RATE_SCALE);
                        //单户加权存款利率 = a * 单户存款利率
                        return BigDecimalUtils.mul(a,o.getDepositRate(),RATE_SCALE);
                    }).reduce(BigDecimal.ZERO,BigDecimal::add);
            return rate.setScale(RATE_RESULT_SCALE, RoundingMode.HALF_UP);
        }else
        if(IntervalTypeEnum.年度区间.getValue().equals(intervalType)){
            BigDecimal totalAmt = new BigDecimal(acctList.parallelStream()
                    .filter(o -> true)
                    .mapToLong(o -> {
                        BigDecimal avgAmount = BigDecimalUtil.yuanToFen(o.getYearAvgDepositAmount());
                        return avgAmount==null?0:avgAmount.longValue();
                    }).sum());

            BigDecimal rate =
                    acctList.parallelStream()
                            .filter(o -> true)
                            .map(o -> {
                                //a = 单户期间日均余额/sum(期间日均余额)
                                BigDecimal avgDepositAmount = BigDecimalUtil.yuanToFen(o.getYearAvgDepositAmount());
                                BigDecimal a = BigDecimalUtils.div(avgDepositAmount==null?0:avgDepositAmount,totalAmt,RATE_SCALE);
                                //单户加权存款利率 = a * 单户存款利率
                                return BigDecimalUtils.mul(a,o.getYearDepositRate(),RATE_SCALE);
                            }).reduce(BigDecimal.ZERO,BigDecimal::add);
            return rate.setScale(RATE_RESULT_SCALE, RoundingMode.HALF_UP);
        }else {
            throw new BaseException("错误的区间类型");
        }
    }

    /**
     * 模拟付息（单位：分）
     * 公式：期间日均余额合计 * 期间加权利率
     */
    public static BigDecimal payInterest(BigDecimal avgAmtSum,BigDecimal weightRate){
        return BigDecimalUtils.mul(avgAmtSum,weightRate,0);
    }

}
